﻿namespace UnityEditor
{
    using System;
    using System.Runtime.CompilerServices;
    using UnityEngine;

    internal class ModelImporterRigEditor : AssetImporterInspector
    {
        private const float kDeleteWidth = 17f;
        private SerializedProperty m_AdditionalBone;
        private SerializedProperty m_AnimationType;
        private Avatar m_Avatar;
        private bool m_AvatarCopyIsUpToDate;
        private SerializedProperty m_AvatarSource;
        private ReorderableList m_ClipList;
        private SerializedProperty m_CopyAvatar;
        private SerializedProperty m_LegacyGenerateAnimations;
        private string[] m_RootMotionBoneList;
        private SerializedProperty m_RootMotionBoneName;
        public int m_SelectedClipIndex = -1;
        private static Styles styles;

        private void AvatarAutoSetupOrClear()
        {
            if (this.UsesOwnHumanoidAvatar())
            {
                AvatarSetupTool.AutoSetupOnInstance(base.assetEditor.target as GameObject, base.serializedObject);
            }
            else
            {
                AvatarSetupTool.ClearAll(base.serializedObject);
            }
        }

        private void CheckIfAvatarCopyIsUpToDate()
        {
            if ((this.animationType != ModelImporterAnimationType.Human) || (this.m_AvatarSource.objectReferenceValue == null))
            {
                this.m_AvatarCopyIsUpToDate = true;
            }
            else
            {
                ModelImporter atPath = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(this.m_AvatarSource.objectReferenceValue)) as ModelImporter;
                this.m_AvatarCopyIsUpToDate = DoesHumanDescriptionMatch(this.singleImporter, atPath);
            }
        }

        private void ConfigureAvatarGUI()
        {
            if (base.targets.Length > 1)
            {
                GUILayout.Label("Can't configure avatar in multi-editing mode", EditorStyles.helpBox, new GUILayoutOption[0]);
            }
            else if (this.singleImporter.transformPaths.Length <= HumanTrait.RequiredBoneCount)
            {
                GUILayout.Label("Not enough bones to create human avatar (requires " + HumanTrait.RequiredBoneCount + ")", EditorStyles.helpBox, new GUILayoutOption[0]);
            }
            else
            {
                GUIContent avatarValid;
                if ((this.m_Avatar != null) && !this.HasModified())
                {
                    if (this.m_Avatar.isHuman)
                    {
                        avatarValid = styles.avatarValid;
                    }
                    else
                    {
                        avatarValid = styles.avatarInvalid;
                    }
                }
                else
                {
                    avatarValid = styles.avatarPending;
                    GUILayout.Label("The avatar can be configured after settings have been applied.", EditorStyles.helpBox, new GUILayoutOption[0]);
                }
                Rect controlRect = EditorGUILayout.GetControlRect(new GUILayoutOption[0]);
                GUI.Label(new Rect((controlRect.xMax - 75f) - 18f, controlRect.y, 18f, controlRect.height), avatarValid, EditorStyles.label);
                EditorGUI.BeginDisabledGroup(this.m_Avatar == null);
                if (GUI.Button(new Rect(controlRect.xMax - 75f, controlRect.y + 1f, 75f, controlRect.height - 1f), styles.configureAvatar, EditorStyles.miniButton))
                {
                    if (!this.isLocked)
                    {
                        if (EditorApplication.SaveCurrentSceneIfUserWantsTo())
                        {
                            Selection.activeObject = this.m_Avatar;
                            AvatarEditor.s_EditImmediatelyOnNextOpen = true;
                        }
                    }
                    else
                    {
                        Debug.Log("Cannot configure avatar, inspector is locked");
                    }
                }
                EditorGUI.EndDisabledGroup();
            }
        }

        private void CopyAvatarGUI()
        {
            GUILayout.Label("If you have already created an Avatar for another model with a rig identical to this one, you can copy its Avatar definition.\nWith this option, this model will not support animation. It will only be used as a source for importing animations.", EditorStyles.helpBox, new GUILayoutOption[0]);
            EditorGUILayout.BeginHorizontal(new GUILayoutOption[0]);
            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(this.m_AvatarSource, GUIContent.Temp("Source"), new GUILayoutOption[0]);
            Avatar objectReferenceValue = this.m_AvatarSource.objectReferenceValue as Avatar;
            if (EditorGUI.EndChangeCheck())
            {
                AvatarSetupTool.ClearAll(base.serializedObject);
                if (objectReferenceValue != null)
                {
                    this.CopyHumanDescriptionFromOtherModel(objectReferenceValue);
                }
                this.m_AvatarCopyIsUpToDate = true;
            }
            if (((objectReferenceValue != null) && !this.m_AvatarSource.hasMultipleDifferentValues) && (!this.m_AvatarCopyIsUpToDate && GUILayout.Button(styles.updateMuscleDefinitionFromSource, EditorStyles.miniButton, new GUILayoutOption[0])))
            {
                AvatarSetupTool.ClearAll(base.serializedObject);
                this.CopyHumanDescriptionFromOtherModel(objectReferenceValue);
                this.m_AvatarCopyIsUpToDate = true;
            }
            EditorGUILayout.EndHorizontal();
        }

        private void CopyHumanDescriptionFromOtherModel(Avatar sourceAvatar)
        {
            SerializedObject modelImporterSerializedObject = GetModelImporterSerializedObject(AssetDatabase.GetAssetPath(sourceAvatar));
            CopyHumanDescriptionToDestination(modelImporterSerializedObject, base.serializedObject);
            modelImporterSerializedObject.Dispose();
        }

        private static void CopyHumanDescriptionToDestination(SerializedObject sourceObject, SerializedObject targetObject)
        {
            targetObject.CopyFromSerializedProperty(sourceObject.FindProperty("m_HumanDescription"));
        }

        private void CopyHumanDescriptionToOtherModel(string otherModelImporterPath)
        {
            SerializedObject modelImporterSerializedObject = GetModelImporterSerializedObject(otherModelImporterPath);
            CopyHumanDescriptionToDestination(base.serializedObject, modelImporterSerializedObject);
            modelImporterSerializedObject.Dispose();
        }

        private static bool DoesHumanDescriptionMatch(ModelImporter importer, ModelImporter otherImporter)
        {
            UnityEngine.Object[] objs = new UnityEngine.Object[] { importer, otherImporter };
            SerializedObject obj2 = new SerializedObject(objs);
            bool flag = !obj2.FindProperty("m_HumanDescription").hasMultipleDifferentValues;
            obj2.Dispose();
            return flag;
        }

        private void GenericGUI()
        {
            EditorGUI.BeginChangeCheck();
            this.rootIndex = EditorGUILayout.Popup("Root node", this.rootIndex, this.m_RootMotionBoneList, new GUILayoutOption[0]);
            if (EditorGUI.EndChangeCheck())
            {
                if ((this.rootIndex > 0) && (this.rootIndex < this.m_RootMotionBoneList.Length))
                {
                    this.m_RootMotionBoneName.stringValue = FileUtil.GetLastPathNameComponent(this.m_RootMotionBoneList[this.rootIndex]);
                }
                else
                {
                    this.m_RootMotionBoneName.stringValue = string.Empty;
                }
            }
        }

        private static SerializedObject GetModelImporterSerializedObject(string assetPath)
        {
            ModelImporter atPath = AssetImporter.GetAtPath(assetPath) as ModelImporter;
            if (atPath == null)
            {
                return null;
            }
            return new SerializedObject(atPath);
        }

        private void HumanoidGUI()
        {
            EditorGUI.BeginChangeCheck();
            int selectedIndex = !this.m_CopyAvatar.boolValue ? 0 : 1;
            EditorGUI.showMixedValue = this.m_CopyAvatar.hasMultipleDifferentValues;
            string[] displayedOptions = new string[] { "Create From This Model", "Copy From Other Avatar" };
            selectedIndex = EditorGUILayout.Popup("Avatar Definition", selectedIndex, displayedOptions, new GUILayoutOption[0]);
            EditorGUI.showMixedValue = false;
            if (EditorGUI.EndChangeCheck())
            {
                this.m_CopyAvatar.boolValue = selectedIndex == 1;
            }
            if (!this.m_CopyAvatar.hasMultipleDifferentValues)
            {
                if (!this.m_CopyAvatar.boolValue)
                {
                    this.ConfigureAvatarGUI();
                }
                else
                {
                    this.CopyAvatarGUI();
                }
            }
            EditorGUILayout.Space();
            EditorGUILayout.PropertyField(this.m_AdditionalBone, styles.AdditionalBone, new GUILayoutOption[0]);
        }

        private void LegacyGUI()
        {
            EditorGUILayout.Popup(this.m_LegacyGenerateAnimations, styles.AnimationsOpt, new GUIContent("Generation"), new GUILayoutOption[0]);
            if (((this.m_LegacyGenerateAnimations.intValue == 1) || (this.m_LegacyGenerateAnimations.intValue == 2)) || (this.m_LegacyGenerateAnimations.intValue == 3))
            {
                EditorGUILayout.HelpBox("The animation import setting \"" + styles.AnimationsOpt[this.m_LegacyGenerateAnimations.intValue].text + "\" is deprecated.", MessageType.Warning);
            }
        }

        public void OnEnable()
        {
            this.m_AnimationType = base.serializedObject.FindProperty("m_AnimationType");
            this.m_AdditionalBone = base.serializedObject.FindProperty("m_AdditionalBone");
            this.m_AvatarSource = base.serializedObject.FindProperty("m_LastHumanDescriptionAvatarSource");
            this.m_RootMotionBoneName = base.serializedObject.FindProperty("m_HumanDescription.m_RootMotionBoneName");
            this.m_RootMotionBoneList = this.singleImporter.transformPaths;
            if (this.m_RootMotionBoneList.Length > 0)
            {
                this.m_RootMotionBoneList[0] = "None";
            }
            this.rootIndex = ArrayUtility.FindIndex<string>(this.m_RootMotionBoneList, s => FileUtil.GetLastPathNameComponent(s) == this.m_RootMotionBoneName.stringValue);
            this.rootIndex = (this.rootIndex >= 1) ? this.rootIndex : 0;
            this.m_CopyAvatar = base.serializedObject.FindProperty("m_CopyAvatar");
            this.m_LegacyGenerateAnimations = base.serializedObject.FindProperty("m_LegacyGenerateAnimations");
            this.CheckIfAvatarCopyIsUpToDate();
        }

        public override void OnInspectorGUI()
        {
            if (styles == null)
            {
                styles = new Styles();
            }
            bool flag = this.UsesOwnHumanoidAvatar();
            EditorGUILayout.PropertyField(this.m_AnimationType, new GUILayoutOption[0]);
            EditorGUILayout.Space();
            if (!this.m_AnimationType.hasMultipleDifferentValues)
            {
                if (this.animationType == ModelImporterAnimationType.Human)
                {
                    this.HumanoidGUI();
                }
                else if (this.animationType == ModelImporterAnimationType.Generic)
                {
                    this.GenericGUI();
                }
                else if (this.animationType == ModelImporterAnimationType.Legacy)
                {
                    this.LegacyGUI();
                }
            }
            if (this.UsesOwnHumanoidAvatar() != flag)
            {
                this.AvatarAutoSetupOrClear();
            }
            if (((this.m_Avatar != null) && this.m_Avatar.isValid) && this.m_Avatar.isHuman)
            {
                this.ShowUpdateReferenceClip();
            }
            base.ApplyRevertGUI();
        }

        internal override void ResetValues()
        {
            base.ResetValues();
            this.m_Avatar = AssetDatabase.LoadAssetAtPath((base.target as ModelImporter).assetPath, typeof(Avatar)) as Avatar;
        }

        private void ShowUpdateReferenceClip()
        {
            bool flag = false;
            foreach (ModelImporter importer in base.targets)
            {
                if (importer.referencedClips.Length <= 0)
                {
                    continue;
                }
                string[] referencedClips = importer.referencedClips;
                int index = 0;
                while (index < referencedClips.Length)
                {
                    string guid = referencedClips[index];
                    ModelImporter atPath = AssetImporter.GetAtPath(AssetDatabase.GUIDToAssetPath(guid)) as ModelImporter;
                    flag = !DoesHumanDescriptionMatch(importer, atPath);
                    break;
                }
                if (flag)
                {
                    break;
                }
            }
            if (flag && GUILayout.Button("Update reference clips", new GUILayoutOption[0]))
            {
                foreach (ModelImporter importer3 in base.targets)
                {
                    foreach (string str3 in importer3.referencedClips)
                    {
                        string otherModelImporterPath = AssetDatabase.GUIDToAssetPath(str3);
                        this.CopyHumanDescriptionToOtherModel(otherModelImporterPath);
                        AssetDatabase.ImportAsset(otherModelImporterPath);
                    }
                }
            }
        }

        private bool UsesOwnHumanoidAvatar()
        {
            if (this.animationType != ModelImporterAnimationType.Human)
            {
                return false;
            }
            if (this.m_CopyAvatar.boolValue)
            {
                return false;
            }
            return true;
        }

        private ModelImporterAnimationType animationType
        {
            get
            {
                return (ModelImporterAnimationType) this.m_AnimationType.intValue;
            }
            set
            {
                this.m_AnimationType.intValue = (int) value;
            }
        }

        public bool isLocked
        {
            get
            {
                foreach (InspectorWindow window in InspectorWindow.GetAllInspectorWindows())
                {
                    foreach (Editor editor in window.GetTracker().activeEditors)
                    {
                        if (editor == this)
                        {
                            return window.isLocked;
                        }
                    }
                }
                return false;
            }
        }

        public int rootIndex { get; set; }

        private ModelImporter singleImporter
        {
            get
            {
                return (base.targets[0] as ModelImporter);
            }
        }

        private class Styles
        {
            public GUIContent AdditionalBone = new GUIContent("Keep Additional Bones", "Uncheck to remove all the transfrom that doesn't have any human child transform. If you know that you won't have animation on those transform uncheck this option to reduce the size of your avatar.");
            public GUIContent Animations = EditorGUIUtility.TextContent("ModelImporterAnimations");
            public GUIContent[] AnimationsOpt = new GUIContent[] { EditorGUIUtility.TextContent("ModelImporterAnimNone"), EditorGUIUtility.TextContent("ModelImporterAnimOrigRoot"), EditorGUIUtility.TextContent("ModelImporterAnimNode"), EditorGUIUtility.TextContent("ModelImporterAnimRoot"), EditorGUIUtility.TextContent("ModelImporterAnimRootNew") };
            public GUIContent AnimLabel = EditorGUIUtility.TextContent("ModelImporterAnimLabel");
            public GUIContent avatar = new GUIContent("Animator");
            public GUIContent avatarInvalid = EditorGUIUtility.TextContent("✕");
            public GUIContent avatarPending = EditorGUIUtility.TextContent("...");
            public GUIContent avatarValid = EditorGUIUtility.TextContent("✓");
            public GUIContent configureAvatar = EditorGUIUtility.TextContent("Configure...");
            public GUIStyle helpText = new GUIStyle(EditorStyles.helpBox);
            public GUIContent muscleDef = new GUIContent("Human Definition", "Human animation data can be generated if a human Avatar definition is available.");
            public GUIContent updateMuscleDefinitionFromSource = new GUIContent("Update", "Update the copy of the muscle definition from the source.");

            public Styles()
            {
                this.helpText.normal.background = null;
                this.helpText.alignment = TextAnchor.MiddleLeft;
                this.helpText.padding = new RectOffset(0, 0, 0, 0);
            }
        }
    }
}

